package com.example.service.impl;

import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.mapper.GpsAssociation;
import com.example.mapper.SbMessageMapper;
import com.example.pojo.GpsAssociationVo;
import com.example.pojo.LoginUser;
import com.example.pojo.ResponseVo;
import com.example.pojo.SbMessageVo;
import com.example.service.SbMessageService;
import com.example.util.GPSTransToAMapUtil;
import com.example.util.Sample;
import com.example.util.SecurityUtil;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.beans.Transient;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Service
public class SbMessageServiceImpl  implements SbMessageService {

    @Autowired
    private SbMessageMapper sbMessageMapper;

    @Autowired
    private GpsAssociation gpsAssociation;

    private  ExecutorService executorService = Executors.newFixedThreadPool(5);

    @Override
    public ResponseVo UserSbMeesage() {
        String username = SecurityUtil.getUsername();
      List<SbMessageVo> sbMessageVos = sbMessageMapper.UserSbMessage(username);
        return ResponseVo.success(sbMessageVos);
    }
    @Override
    public ResponseVo devicLocation(String sbid) {
        SbMessageVo map= sbMessageMapper.devicLocation(sbid);
       if (map==null)
           return ResponseVo.no("未查询到位置信息");
       if (new Date().getTime()>map.getPeriodOfValidity().getTime())
           return ResponseVo.no("该设备已过期");
        GPSTransToAMapUtil.AMap transform = GPSTransToAMapUtil.transform(map.getLongitude(), map.getLatitude());
        System.out.println("GPS转高德之后：" + transform.getLongitude() + "," + transform.getLatitude());
        map.setLatitude(transform.getLatitude());
        map.setLongitude(transform.getLongitude());
        return ResponseVo.success(map);
    }
    @Override
    public ResponseVo deviceTrackPlayBack(String sbid, String startTime, String endTime) {
        List<Map<String,Double>> maps=sbMessageMapper.deviceTrackPlayBack(sbid,startTime,endTime);
        for (Map<String, Double> map : maps) {
            double latitude = map.get("latitude");
            double longitude = map.get("longitude");
            GPSTransToAMapUtil.AMap transform = GPSTransToAMapUtil.transform(longitude,latitude );
            map.put("latitude",transform.getLatitude());
            map.put("longitude",transform.getLongitude());
        }
        return ResponseVo.success(maps);
    }

    @Transactional(rollbackFor = Exception.class)
    public ResponseVo insert(SbMessageVo message) {
        String username = SecurityUtil.getUsername();
       LoginUser loginUser = sbMessageMapper.selectUserInfo(username);
        sbMessageMapper.insert(message);
        GpsAssociationVo gpsAssociationVo = new GpsAssociationVo();
        gpsAssociationVo.setUserid(loginUser.getId());
        gpsAssociationVo.setImei(message.getImei());
        gpsAssociation.insert(gpsAssociationVo);
        return ResponseVo.success("保存成功");
    }


    @Transactional(rollbackFor = Exception.class)
    public ResponseVo deleteById(Long id) {
        sbMessageMapper.deleteById(id);
        QueryWrapper<GpsAssociationVo> gpsAssociationVoQueryWrapper = new QueryWrapper<>();
        gpsAssociationVoQueryWrapper.eq("imei",id);
        gpsAssociation.delete(gpsAssociationVoQueryWrapper);
        return ResponseVo.success("删除成功");
    }


    @Transactional(rollbackFor = Exception.class)
    public ResponseVo updateById(SbMessageVo message) {
        sbMessageMapper.updateById(message);
        return ResponseVo.success("更新成功");
    }

    private static final double EARTH_RADIUS = 6371.0; // 地球半径，单位为公里

    public static double calculateDistance(List<Map<String,Double>> list) {
        double lat1=0;
        double lon1=0;
        double lat2=0;
        double lon2=0;
        double mileage=0;
        for (int i = 0; i < list.size()-1; i++) {

            lat1 = list.get(i).get("latitude");
            lon1 = list.get(i).get("longitude");

            lat2 = list.get(i+1).get("latitude");
            lon2 = list.get(i+1).get("longitude");
        double dLat = Math.toRadians(lat2 - lat1);
        double dLon = Math.toRadians(lon2 - lon1);

        double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
                Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
                        Math.sin(dLon / 2) * Math.sin(dLon / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        mileage+=(EARTH_RADIUS * c);
        }
       return Math.round(mileage);
    }



    public static double calculateDistance(double lat1,double lon1,double lat2,double lon2) {

        double mileage=0;
            double dLat = Math.toRadians(lat2 - lat1);
            double dLon = Math.toRadians(lon2 - lon1);
            double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
                    Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
                            Math.sin(dLon / 2) * Math.sin(dLon / 2);
            double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
            mileage+=(EARTH_RADIUS * c);
        return Math.round(mileage);
    }


    @Override
    public ResponseVo MileageStatistics(String sbid) {
        List<Map<String,Double>> imei = sbMessageMapper.selectGpsDate(sbid);
        return ResponseVo.success(calculateDistance(imei)+"公里");
    }

    @Override
    public ResponseVo ElectronicFenceInformation(String sbid) {
     List<Map<String, Object>> list = sbMessageMapper.seletElectronicFenceInformation(sbid);
        return ResponseVo.success(list);
    }

    @Autowired
    private Sample sample;

    @Override
    public ResponseVo openElectronicFenceInformation(String sbid) {
        sbMessageMapper.updateElect(sbid,"1");
        executorService.execute(new Runnable() {
            boolean sfqy=true;
            @SneakyThrows
            @Override
            public void run() {
                while (sfqy) {
                    Map<String, Object> map = sbMessageMapper.seletOpenElectronicFenceInformation(sbid);
                    sfqy = map.get("sfqy").equals("1") ? true : false;
                    double lon2 = (double)map.get("center_point_coordinates_longitude");
                    double lat2 = (double)map.get("center_point_coordinates_latitude");
                    SbMessageVo sbMessageVo = sbMessageMapper.devicLocation(sbid);
                    GPSTransToAMapUtil.transform(sbMessageVo.getLongitude(),sbMessageVo.getLatitude());
                    double v = calculateDistance(sbMessageVo.getLatitude(), sbMessageVo.getLongitude(), lat2, lon2);
                    double s = Double.parseDouble((String) map.get("radius"));
                    if (v > s) {
                        LoginUser loginUser = sbMessageMapper.getDeviceUser(sbid);
                        SendSmsResponse sendSmsResponse = sample.sendSms(loginUser.getPhoneNum(), "");
                       if(!"OK".equals(sendSmsResponse.body.code)) {
                           sfqy = false;
                           throw new Exception(sendSmsResponse.body.message);
                       }
                        Thread.sleep(60000*60);
                    }else{
                        Thread.sleep(60000*5);
                    }
                }
            }
        });
        return ResponseVo.success("打开成功");
}

    @Override
    public ResponseVo closeElectronicFenceInformation(String sbid) {
        sbMessageMapper.updateElect(sbid,"0");
        return ResponseVo.success("关闭成功");
    }

    @Override
    public ResponseVo SaveElectronicFenceInformation(Map<String, String> map) {
           sbMessageMapper.deleteElectIcInformation(map.get("imei"));
            sbMessageMapper.SaveElectronicFenceInformation(map);
        return ResponseVo.success("保存成功");
    }

    @Override
    public ResponseVo openState(String sbid) {
      String kqzt=  sbMessageMapper.openState(sbid);
        return ResponseVo.success(kqzt);
    }


}
